package sel.me.spring.boot159.web.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author shenenlu 2021年01月14日 上午11:07:12
 */
@Aspect
@Component
public class SysLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定义一个方法描述切点
     */
    @Pointcut(value = "execution(public String test (..))")
    public void cutOffPoint() {

    }

    /**
     * 定义注解切点
     */
    @Pointcut(value = "@annotation(operationLog)")
    public void annotationPoint(OperationLog operationLog) {

    }

    @Before("cutOffPoint()")
    public void beforeTest(JoinPoint joinPoint){
        logger.info("我在test方法之前执行, {}", joinPoint);
    }

    @After("cutOffPoint()")
    public void doAfter(JoinPoint joinPoint){
        logger.info("我是在test之后执行的, {}",  joinPoint);
    }

    @Around("cutOffPoint()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        startTime.set(System.currentTimeMillis());
        logger.info("我是环绕通知执行");
        String methodName = pjp.getSignature().getName();
        logger.info(methodName+"参数 : {}" , pjp.getArgs());
//        try{
        Object obj = pjp.proceed();
            logger.info(methodName+"执行返回值 : {}" , obj);
            logger.info(methodName+"方法执行耗时: " + (System.currentTimeMillis() - startTime.get()));
//        } catch (Throwable throwable) {
//            obj=throwable.toString();
//        }
        return obj;
    }



    @Around("annotationPoint(operationLog)")
    public Object doAroundAnnotation(ProceedingJoinPoint pjp, OperationLog operationLog) throws Throwable {
        startTime.set(System.currentTimeMillis());
        logger.info("我是注解环绕通知执行");
        logger.info("注解: " + operationLog.annotationType().getName()
                + " " + operationLog.message() + " " + operationLog.operation());

        String methodName = pjp.getSignature().getName();
        logger.info(methodName+"参数 : {}" , pjp.getArgs());
//        try{
        Object obj = pjp.proceed();
        logger.info(methodName+"执行返回值 : {}" , obj);
        logger.info(methodName+"方法执行耗时: " + (System.currentTimeMillis() - startTime.get()));
//        } catch (Throwable throwable) {
//            obj=throwable.toString();
//        }
        return obj;
    }
}
